package main

import (
	"fmt"
	"reflect"
)

// 切片传的是引用
func changeSlice(s []int) {
	s[0] = 1111 // 切片是对一个地址的引用,所以传的是引用.当内容变更,数据自然也会发生变化
}

// 切片的包含三个部分
// 1、一个地址的引用
// 2、长度
// 3、容量
func main() {
	arr := [...]int{0, 1, 2, 3, 4} // 也是数组,...表示自动获取数组长度
	s1 := arr[2:4]                 // 此时s1是arr数组的一个映射.
	changeSlice(s1)
	fmt.Println(s1, reflect.TypeOf(s1)) //[1111 3] []int

	s2 := s1[1:3]
	// s2 是对s1的映射,但s1的底层是arr,所以本质还是对arr的映射.只是切片的开始是基于s1的而已.但结尾不能越过arr,否则会报错
	fmt.Println(s2, reflect.TypeOf(s2)) // [3 4] []int

	s2[1] = 222      // s1 和 s2 都是对arr数组的引用,所以改变的也是数组
	fmt.Println(arr) //[0 1 1111 3 222]

	s2 = append(s2, 5555)
	// 因为s2 本是切片(切片可以追加数据),而arr数组(数据不可以追加数据).
	// 所以s2会另起炉灶,会先创建一个内存空间将s2 的引用数据复制进去,再将5555追加进去
	// 此时的s2 引用地址指向的是另一个内存空间
	fmt.Println(s2)  // [3 222 5555]
	fmt.Println(arr) //[0 1 1111 3 222]

	s2[0] = 123123123
	// 证明此时的s2 已经不在映射数组的内存空间了,而是重新创建了一个内容空间
	fmt.Println(s2)  //[123123123 222 5555]
	fmt.Println(arr) //[0 1 1111 3 222]

}
